package com.blue.integration.spring.redis;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 单键值缓存
 *
 * @author zhengjin
 * @since 1.0 2018年06月23日
 */
public abstract class AbstractValueCache<T, V>
{
	private static Logger logger = LoggerFactory.getLogger(AbstractValueCache.class);
	@Resource
	protected RedisCache redisCache;

	private Class<T> cacheClazz;
	private Class<V> cacheItemClazz;

	@SuppressWarnings("unchecked")
	public AbstractValueCache()
	{
		Type[] types = ((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments();
		cacheClazz = (Class<T>) types[0];
		cacheItemClazz = (Class<V>) types[1];
	}

	public final void delete(Object id)
	{
		String key = this.getKey(id);
		redisCache.delete(key);
	}

	protected final V getCacheItem(Object id)
	{
		String key = this.getKey(id);
		V item = redisCache.get(key);
		if (item == null)
		{
			redisCache.lock(key);
			try
			{
				item = redisCache.get(key);
				if (item == null)
				{
					item = (V)cacheItemClazz.newInstance();
					this.initCacheItem(item, id);
					redisCache.set(key, item, this.getExpireHour(), TimeUnit.HOURS);
				}
			}
			catch (Exception e)
			{
				logger.info("初始化类失败：" + cacheItemClazz.getName(), e);
			}
			finally
			{
				redisCache.unlock(key);
			}
		}
		return item;
	}

	/**
	 * 返回过期时间，默认1小时
	 */
	protected int getExpireHour()
	{
		return 1;
	}

	/**
	 * 从数据库中初始化缓存项
	 */
	protected abstract void initCacheItem(V item, Object id);

	/**
	 * 获取键
	 */
	protected abstract String getKey(Object id);

}
